import { useEffect, useState, useCallback, useRef, createElement } from 'react';
import { DownOutlined, CloseCircleFilled } from '@ant-design/icons';
import { Key } from 'antd/es/table/interface';
import { Empty, Modal, Input, Spin, message, Checkbox, Tree } from 'antd';
import { TextWidget, getMessage } from '@inbiz/react';
import { request, InbizIcon, pageGroupOneToTwo, useApp, RenderModalToBody, getNowPageRoute } from '@inbiz/utils';
import { observer } from '@formily/react';
import Pagination from '@inbiz/basic/Pagination';
import { getGroupList, getGroupPageList, getPermTree } from './service';
import './index.less';

export async function getPageTree(appInfo: any) {
  return request(
    `/inbiz/api/services/engines/v${InbizConfig.API_VERSION}/page/loadTreeList`,
    {
      params: {
        siteOutId: appInfo?.OutId,
        dataVersionId: appInfo?.SiteInfo?.DataVersionId,
        appId: appInfo?.AppId,
      },
    },
  );
}

// 扁平化
export const tileTree = (list: any) => {
  const newArr = list.reduce(function (pre: any, cur: any) {
    if (cur.Children) {
      const child = cur.Children;
      delete cur.Children;
      return pre.concat(cur).concat(child);
    }
    return pre.concat(cur);
  }, []);

  if (newArr.length < 1) return [];
  return newArr.filter((item: any) => !item.IsGroup);
};

/** 页面选择弹窗组件 */
const PagePicker = observer((props: {
  value?: string | null;
  isMenu?: boolean;
  notSelectNowPage?: boolean;
  clear?: 'false';
  range?: 'all';
  client?: 'web' | 'wap'; // 默认web
  disabled?: boolean;
  hideSelectVisible?: boolean;
  onChange?: (e: string) => void;
  onBlur?: () => void;
  onCancel?: () => void;
}) => {
  const appInfo = useApp();
  const { isMenu, range, client, disabled, hideSelectVisible, notSelectNowPage, onChange, onBlur, onCancel, ...otherProps } =
    props;
  // model显示控制
  const [visible, $visible] = useState<boolean>(Boolean(hideSelectVisible));
  // 当前选中分组
  const [activeGroup, $activeGroup] = useState('');
  // 当前选中页面
  const [activePage, $activePage] = useState<any>(null);
  // 当前选中页面名
  const [activePageName, $activePageName] = useState('');
  // 当前选中页面详情
  const [activeInfo, $activeInfo] = useState<any>(null);
  // 组列表数据
  const [groupList, $groupList] = useState<any[]>([]);
  // 页面列表数据
  const [dataSource, $dataSource] = useState<any[]>([]);
  // 页面总数
  const [pageTotal, $pageTotal] = useState<number>(0);
  // 组列表加载
  const [groupLoading, $groupLoading] = useState<boolean>(false);
  // 页面列表加载
  const [pageLoading, $pageLoading] = useState<boolean>(false);
  // 当前页码
  const [current, $current] = useState<number>(1);
  // 当前分页数值
  const [pageSize, $pageSize] = useState<number>(10);
  // 分组数据获取状态（是否成功）
  const [loadGroup, $loadGroup] = useState<boolean>(false);
  // 搜索框文本
  const [searchIpts, $searchIpts] = useState<string>('');
  // 是否全局搜索
  const [searchAll, $searchAll] = useState<boolean>(true);
  // 组件最外层div的dom
  const selectRef: any = useRef();
  // 搜索框Dom
  const searchRef: any = useRef();

  // app名称
  const appName = appInfo.Name;

  // 需要失焦事件时先获得焦点
  useEffect(() => {
    onBlur && selectRef.current?.focus();
  }, [onBlur])

  // 初始化获取分组列表
  useEffect(() => {
    $groupLoading(true);
    if (range !== 'all') {
      getGroupList({
        siteOutId: appInfo.OutId,
        dataVersionId: appInfo.DataVersionId,
        appId: appInfo.appId,
      })
        .then(async (res) => {
          if (Array.isArray(res)) {
            let list: any[] = await pageGroupOneToTwo(res);
            $groupList(list);
            $loadGroup(true);
          }
          $groupLoading(false);
        })
        .catch(() => $groupLoading(false));
    } else {
      getPermTree({
        isQuerySite: true,
        siteType: client === 'wap' ? 1 : 0,
        appId: ' ',
      })
        .then((res: any) => {
          if (Array.isArray(res)) {
            let arr: any[] = res.filter(
              (item: any) => item.DisplayName && item.Route,
            );
            if (arr.length) {
              $activeGroup(arr[0].AppId);
              nowAppInfo.current = {
                appId: arr[0].AppId,
                siteOutId: arr[0].SiteOutId,
                dataVersionId: arr[0].DataVersionId,
                route: arr[0].Route,
                parentId: '',
              };
              if (!arr[0].Children) {
                getAppGroupList(
                  arr[0].AppId,
                  arr[0].SiteOutId,
                  arr[0].DataVersionId,
                  arr,
                );
              }
              $loadGroup(true);
            } else {
              $appList(arr);
              $loadGroup(true);
            }
          }
          $groupLoading(false);
        })
        .catch(() => $groupLoading(false));
    }
  }, [range]);

  // 组变化获取页面列表数据
  useEffect(() => {
    $current(1);
    if (!loadGroup) {
      return;
    }
    if (range === 'all' && !nowAppInfo.current.appId) {
      return;
    }
    $pageLoading(true);
    let params =
      range === 'all'
        ? {
          siteOutId: nowAppInfo.current.siteOutId,
          dataVersionId: nowAppInfo.current.dataVersionId,
          appId: nowAppInfo.current.appId,
          parentId: nowAppInfo.current.parentId,
          skipCount: 0,
          maxResultCount: pageSize,
          all: true,
          isTranslate: true
        }
        : {
          siteOutId: appInfo.OutId,
          dataVersionId: appInfo.DataVersionId,
          appId: appInfo.appId,
          parentId: activeGroup,
          skipCount: 0,
          maxResultCount: pageSize,
          all: false,
          isTranslate: true
        };
    getGroupPageList(params)
      .then((res) => {
        if (Array.isArray(res.Data)) {
          $dataSource(res.Data);
          $pageTotal(res.Total);
        }
        $pageLoading(false);
      })
      .catch(() => $pageLoading(false));
  }, [activeGroup, loadGroup]);

  // 回填value
  useEffect(() => {
    let value = props.value;
    if (value && typeof value === 'string' && value !== '') {
      let arr = value.split(',');
      if (range === 'all') {
        let [v1, v2, v3, v4, v5, v6] = arr;
        if (v1 && v2 && v3 && v4 && v5 && v6) {
          if (notSelectNowPage && v5 === getNowPageRoute()) {
            $activePage(null);
            $activeInfo(null);
            $activePageName('');
            return
          }
          $activePage(v5?.replace('page/', ''));
          $activePageName(v6);
          $activeInfo({
            Route: v5?.replace('page/', ''),
            OutId: v1,
            Name: v6,
          });
          nowAppInfo.current = {
            appId: v4,
            siteOutId: v3,
            route: v2,
            parentId: '',
          };
        } else {
          $activePage(null);
          $activeInfo(null);
          $activePageName('');
        }
      } else {
        if (arr[0] && arr[1] && arr[2]) {
          if (notSelectNowPage && arr[0] === getNowPageRoute()) {
            $activePage(null);
            $activeInfo(null);
            $activePageName('');
            return
          }
          $activePage(arr[0]?.replace('page/', ''));
          $activePageName(arr[2]);
          $activeInfo({
            Route: arr[0]?.replace('page/', ''),
            OutId: arr[1],
            Name: arr[2],
          });
        } else {
          $activePage(null);
          $activeInfo(null);
          $activePageName('');
        }
      }
    } else {
      $activePage(null);
      $activeInfo(null);
      $activePageName('');
    }
  }, [props.value]);

  // 搜索页面
  const searchPage = useCallback(
    (searchIpts: string) => {
      if (!loadGroup) {
        return;
      }
      if (range === 'all' && !nowAppInfo.current.appId) {
        message.info('请选择分组');
        return;
      }
      $pageLoading(true);
      let params =
        range === 'all'
          ? {
            siteOutId: nowAppInfo.current.siteOutId,
            dataVersionId: nowAppInfo.current.dataVersionId,
            appId: nowAppInfo.current.appId,
            parentId: nowAppInfo.current.parentId,
            skipCount: 0,
            maxResultCount: pageSize,
            SearchText: searchIpts?.trim(),
            isSearchAll: searchAll,
            all: true,
            isTranslate: true
          }
          : {
            siteOutId: appInfo.OutId,
            dataVersionId: appInfo.DataVersionId,
            appId: appInfo.appId,
            parentId: activeGroup,
            skipCount: 0,
            maxResultCount: pageSize,
            SearchText: searchIpts?.trim(),
            isSearchAll: searchAll,
            all: false,
            isTranslate: true
          };
      getGroupPageList(params)
        .then((res) => {
          if (Array.isArray(res.Data)) {
            $dataSource(res.Data);
            $pageTotal(res.Total);
          }
          $pageLoading(false);
        })
        .catch(() => $pageLoading(false));
    },
    [loadGroup, pageSize, activeGroup, searchAll],
  );

  // 打开选择弹窗
  const showModal = () => {
    if (disabled) {
      return;
    }
    if (range === 'all') {
      $nowOpenId('');
      if (appList.length && activeGroup !== appList[0].AppId) {
        $activeGroup(appList[0].AppId);
        nowAppInfo.current = {
          appId: appList[0].AppId,
          siteOutId: appList[0].SiteOutId,
          dataVersionId: appList[0].DataVersionId,
          route: appList[0].Route,
          parentId: '',
        };
        if (!appList[0].Children) {
          getAppGroupList(
            appList[0].AppId,
            appList[0].SiteOutId,
            appList[0].DataVersionId,
            appList,
          );
        }
      }
    } else {
      $activeGroup('');
    }
    $searchIpts('');
    $visible(true);
  };

  // 确定
  const handleOk = useCallback(() => {
    if (activeInfo && activePage) {
      let key = '';
      if (range === 'all') {
        let app = nowAppInfo.current;
        key = `${activeInfo.OutId},${app.route},${app.siteOutId},${app.appId},${activeInfo.Route},${activeInfo.Name}`;
      } else {
        key = `${activeInfo.Route},${activeInfo.OutId},${activeInfo.Name}`;
        if (!isMenu) {
          key = 'page/' + key;
        }
      }
      $activePageName(activeInfo.Name);
      onChange && onChange(key);
      $visible(false);
      $activeGroup('*');
    } else {
      message.warning(getMessage('pageselect.message_no_selected')); // 未选择页面
    }
  }, [activePage, activeInfo, isMenu, range]);

  // 选中组
  const clickGroup = (id: any) => {
    if (range === 'all') {
      nowAppInfo.current.parentId = id;
    }
    $activeGroup(id);
    $searchIpts('');
  };

  // 选中页面
  const clickPage = (item: any) => {
    if (notSelectNowPage && item.Route === getNowPageRoute()) {
      message.warning(getMessage('pageselect.not_pick_us'))
      return
    }
    $activePage(item.Route);
    $activeInfo(item);
  };

  // 分页器更新值
  const paginationChange = useCallback(
    (e: any) => {
      $current(e.current);
      $pageSize(e.pageSize);
      if (!loadGroup) {
        return;
      }
      $pageLoading(true);
      let params =
        range === 'all'
          ? {
            siteOutId: nowAppInfo.current.siteOutId,
            dataVersionId: nowAppInfo.current.dataVersionId,
            appId: nowAppInfo.current.appId,
            parentId: nowAppInfo.current.parentId,
            skipCount: (e.current - 1) * e.pageSize,
            maxResultCount: e.pageSize,
            SearchText: searchIpts?.trim(),
            isSearchAll: searchAll,
            all: true,
            isTranslate: true
          }
          : {
            siteOutId: appInfo.OutId,
            dataVersionId: appInfo.DataVersionId,
            appId: appInfo.appId,
            parentId: activeGroup,
            skipCount: (e.current - 1) * e.pageSize,
            maxResultCount: e.pageSize,
            SearchText: searchIpts?.trim(),
            isSearchAll: searchAll,
            all: false,
            isTranslate: true
          };
      getGroupPageList(params)
        .then((res) => {
          if (Array.isArray(res.Data)) {
            $dataSource(res.Data);
            $pageTotal(res.Total);
          }
          $pageLoading(false);
        })
        .catch(() => $pageLoading(false));
    },
    [activeGroup, loadGroup, searchAll],
  );

  // 筛选搜索值更新
  const searchChange = (e: any) => {
    $searchIpts(e.target.value);
  };

  // 清除选中
  const clear = (e: any) => {
    e.stopPropagation();
    onChange?.('');
  };

  // 所有站点数据
  const [appList, $appList] = useState<any[]>([]);
  // 当前打开的站点
  const [nowOpenId, $nowOpenId] = useState<string>('');
  // 当前选中的站点信息
  const nowAppInfo = useRef<any>({});

  // 请求应用下分组
  const getAppGroupList = (
    appId: string,
    siteOutId: string,
    dataVersionId: string,
    arrList?: any[],
  ) => {
    $groupLoading(true);
    getGroupList({
      siteOutId: siteOutId,
      dataVersionId: dataVersionId,
      appId: appId,
      all: true,
    })
      .then(async (res) => {
        if (Array.isArray(res)) {
          let list: any[] = await pageGroupOneToTwo(res);
          let all = arrList || appList;
          const newAppList = all.map((item: any) => {
            let i = { ...item };
            if (i.AppId === appId) {
              i.Children = list;
            } else if (i.Children && i.Children.length) {
              i.Children = null;
            }
            return i;
          });
          $appList(newAppList);
        }
        $groupLoading(false);
      })
      .catch(() => $groupLoading(false));
  };

  return (
    <div
      ref={selectRef}
      tabIndex={-1}
      className={'setter-page-select'}
      {...otherProps}
      onBlur={() => {
        !visible && onBlur?.();
      }}
    >
      <div onClick={showModal} style={{ display: hideSelectVisible ? 'none' : 'flex' }}>
        <div
          className={
            disabled
              ? `${'like-select'} ${'like-select-diable'}`
              : 'like-select'
          }
          d-error="true"
        >
          {activePageName && activePageName !== '' ? (
            <span className={'like-value'}>
              <TextWidget>{activePageName}</TextWidget>
            </span>
          ) : (
            <span className={'like-placeholder'}>
              <TextWidget>pageselect.placeHolder_please_select</TextWidget>{' '}
              {/* 请选择 */}
            </span>
          )}
          {activePageName !== '' && props.clear !== 'false' ? (
            <>
              <DownOutlined
                style={{ color: '#c7c7c7' }}
                className={'more-btn'}
              />
              <div onClick={clear} className={'clear-btn'}>
                <CloseCircleFilled style={{ color: '#c7c7c7' }} />
              </div>
            </>
          ) : (
            <DownOutlined style={{ color: '#c7c7c7' }} />
          )}
        </div>
      </div>
      <Modal
        width={800}
        className={'setter-page-select-model'}
        visible={visible}
        title={getMessage('pageselect.modal_title')} // 页面选择
        okText={getMessage('global.sure')} // 确定
        cancelText={getMessage('global.cancel')} // 取消
        bodyStyle={{ height: 488 }}
        onCancel={() => {
          $visible(false);
          $activeGroup('*');
          onBlur?.();
          onCancel?.()
        }}
        onOk={handleOk}
        destroyOnClose
      >
        <div className={'model-box'}>
          <div className={'content'}>
            <div className={'left-tree'}>
              {/* 非所有站点时显示当前站点 */}
              {range !== 'all' && (
                <p
                  onClick={() => {
                    $activeGroup('');
                    $searchIpts('');
                  }}
                  className={activeGroup === '' ? 'app-selected' : ''}
                >
                  <InbizIcon
                    type="icon-yingyongmingcheng"
                    style={{
                      fontSize: '16px',
                      color: 'var(--inbiz-color-primary)',
                    }}
                  />
                  <span className={'app-name'} title={getMessage(appName)}>
                    <TextWidget>{appName}</TextWidget>
                  </span>
                </p>
              )}
              <Spin spinning={groupLoading}>
                <div className={'left-group-box'}>
                  {range === 'all' ? (
                    appList.map((item: any, idx: number) => {
                      return (
                        <div className={'app-item-box'} key={`${item.OutId}-${idx}`}>
                          <p
                            onClick={() => {
                              if (item.AppId !== activeGroup) {
                                $activeGroup(item.AppId);
                                $searchIpts('');
                                nowAppInfo.current = {
                                  appId: item.AppId,
                                  siteOutId: item.SiteOutId,
                                  dataVersionId: item.DataVersionId,
                                  route: item.Route,
                                  parentId: '',
                                };
                                if (!item.Children) {
                                  getAppGroupList(
                                    item.AppId,
                                    item.SiteOutId,
                                    item.DataVersionId,
                                  );
                                }
                              }
                            }}
                            key={item.AppId}
                            className={`${'app-item-row'} ${activeGroup === item.AppId ? 'app-selected' : ''}`}
                          >
                            <span
                              onClick={(e) => {
                                // e.preventDefault()
                                // e.stopPropagation()
                                if (item.AppId === nowOpenId) {
                                  $nowOpenId('');
                                  return;
                                }
                                $nowOpenId(item.AppId);
                              }}
                              className={
                                nowOpenId === item.AppId
                                  ? `${'app-open-btn'} ${'open-app'}`
                                  : 'app-open-btn'
                              }
                            >
                              {(!item.Children ||
                                Boolean(item.Children.length)) && (
                                  <InbizIcon
                                    type="icon-tree-down"
                                    className={
                                      nowOpenId === item.AppId
                                        ? 'open-app'
                                        : ''
                                    }
                                    style={{ fontSize: '12px', color: '#666' }}
                                  />
                                )}
                            </span>
                            <InbizIcon
                              type="icon-yingyongmingcheng"
                              style={{
                                fontSize: '16px',
                                color: 'var(--inbiz-color-primary)',
                              }}
                            />
                            <span
                              className={'app-name'}
                              title={getMessage(item.DisplayName)}
                            >
                              <TextWidget>{item.DisplayName}</TextWidget>
                            </span>
                          </p>
                          {nowOpenId === item.AppId && (
                            <div className={'app-group-tree'}>
                              {item.Children && (
                                <Tree
                                  showIcon
                                  fieldNames={{
                                    key: 'OutId',
                                    children: 'Children',
                                  }}
                                  onSelect={(keys: Key[]) =>
                                    clickGroup(keys?.[0] || '')
                                  }
                                  selectedKeys={
                                    activeGroup !== '' ? [activeGroup] : []
                                  }
                                  treeData={item.Children}
                                />
                              )}
                            </div>
                          )}
                        </div>
                      );
                    })
                  ) : (
                    <Tree
                      showIcon
                      fieldNames={{
                        key: 'OutId',
                        children: 'Children',
                      }}
                      onSelect={(keys: Key[]) => clickGroup(keys?.[0] || '')}
                      selectedKeys={activeGroup !== '' ? [activeGroup] : []}
                      treeData={groupList}
                    />
                  )}
                </div>
              </Spin>
            </div>
            <div className={'right-nav'}>
              <Spin spinning={pageLoading}>
                <div className={'right-title'}>
                  <Input
                    ref={searchRef}
                    value={searchIpts}
                    onPressEnter={(e: any) => {
                      $current(1);
                      searchPage(e.target.value);
                    }}
                    onChange={searchChange}
                    placeholder={getMessage('pageselect.search_placeholder')} // 请输入页面名称
                    suffix={
                      <InbizIcon
                        type="icon-ic-sousuo"
                        style={{ color: '#999' }}
                        onClick={() => {
                          $current(1);
                          searchPage(searchRef.current?.input?.value || '');
                        }}
                      />
                    }
                  />
                  <Checkbox
                    checked={searchAll}
                    onChange={(e: any) => $searchAll(e.target.checked)}
                  >
                    <TextWidget>pageselect.check_all</TextWidget>{' '}
                    {/* 包含应用内全部页面 */}
                  </Checkbox>
                </div>
                <div className={'page-list'}>
                  <div className={'page-list-header'}>
                    <TextWidget>pageselect.page_nane</TextWidget>{' '}
                    {/* 页面名称 */}
                  </div>
                  {dataSource.length ? (
                    <>
                      <div className={'page-lsit-nav'}>
                        {dataSource.map((item) => {
                          return (
                            <div
                              className={
                                activePage === item.Route
                                  ? `${'list-item'} ${'page-active'}`
                                  : 'list-item'
                              }
                              onClick={() => clickPage(item)}
                              key={item.OutId + item.Route}
                            >
                              <span className='list-item-txt'>
                                <TextWidget>{item.Name}</TextWidget>
                              </span>
                            </div>
                          );
                        })}
                      </div>
                    </>
                  ) : (
                    <Empty
                      image={Empty.PRESENTED_IMAGE_SIMPLE}
                      description={<TextWidget>pageselect.no_data</TextWidget>}
                    />
                  )}
                </div>
                <Pagination
                  size="small"
                  options={[10, 20, 30, 40, 50]}
                  total={pageTotal}
                  current={current}
                  pageSize={pageSize}
                  onChange={paginationChange}
                />
              </Spin>
            </div>
          </div>
        </div>
      </Modal>

    </div>
  );
});

/** 打开页面选择的方法 */
export const openPageSelect: (params?: {
  defaultValue?: string | null;
  notSelectNowPage?: boolean;
  range?: 'all';
  client?: 'web' | 'wap';
}) => Promise<string> = (params: any) => {
  const { defaultValue, ...options } = params
  return new Promise((resolve, reject) => {
    const unmount = RenderModalToBody(
      createElement(PagePicker, {
        ...options,
        value: defaultValue,
        hideSelectVisible: true,
        onChange: (val: string) => {
          unmount()
          resolve(val)
        },
        onCancel: () => {
          unmount()
          reject()
        },
      }),
    );
  })
}

export default PagePicker;
